package org.lhg.activiti.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.lhg.activiti.model.PageBean;
import org.lhg.activiti.util.CommonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/modeler")
public class ModelerController {
    protected static final Logger LOGGER = LoggerFactory.getLogger(ModelerController.class);
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 模型列表分页
     * @param page
     * @param limit
     * @return
     */
    @RequestMapping(value = "/listModeler",method = RequestMethod.GET)
    public CommonResult<JSONObject> listLeave(@RequestParam(value="page",defaultValue="0")String page, @RequestParam(value="limit",defaultValue="0")String limit){
        PageBean pageBean=new PageBean(Integer.parseInt(page),Integer.parseInt(limit));

        ModelQuery modelQuery = repositoryService.createModelQuery();
        modelQuery.orderByLastUpdateTime().desc();

        List<Model> resultList = modelQuery.listPage(pageBean.getStart(),pageBean.getPageSize());

        JSONObject result=new JSONObject();
        JSONArray jsonArr = JSONArray.parseArray(JSON.toJSONString(resultList));
        result.put("rows", jsonArr);
        result.put("total", modelQuery.count());
        return CommonResult.success(result);
    }

    /**
     * 新增模型
     * @param map
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/addModeler",method = RequestMethod.POST)
    public CommonResult<JSONObject> addModel(@RequestBody Map<String,String> map) throws Exception {

        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        Model modelData = repositoryService.newModel();

        ObjectNode modelObjectNode = objectMapper.createObjectNode();
        modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME,map.get("proName") );
        modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);

        modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, map.get("proDesc"));
        modelData.setMetaInfo(modelObjectNode.toString());
        modelData.setName(map.get("proName"));
        modelData.setKey(map.get("proKey"));


        JSONObject jsonObject=new JSONObject();
        //保存模型
        repositoryService.saveModel(modelData);
        repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8"));
        jsonObject.put("modelId",modelData.getId());
        jsonObject.put("success",true);
        return CommonResult.success(jsonObject);
    }

    /**
     * 部署流程
     * @param map
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/deployModeler",method = RequestMethod.POST)
    public CommonResult<JSONObject> deployModel(@RequestBody Map<String,String> map) throws Exception {
        JSONObject jsonObject=new JSONObject();

        Model model = repositoryService.getModel(map.get("modelId"));

        if (model != null) {
            try {
                if (StringUtils.isNotEmpty(model.getMetaInfo())) {
                    //图片流
                    byte[] result =repositoryService.getModelEditorSourceExtra(model.getId());

                    ObjectNode editorJsonNode = (ObjectNode) objectMapper.readTree(
                            new String(repositoryService.getModelEditorSource(model.getId()), "utf-8"));
                    BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
                    BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorJsonNode);
                    //bpmn流
                    byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(bpmnModel);

                    InputStream processNameByte = new ByteArrayInputStream(bpmnBytes);
                    InputStream processPngByte = new ByteArrayInputStream(result);

                   String processName = model.getName() + ".bpmn20.xml";
                   String processPng=model.getName()+".png";

                   //流部署（防止乱码）
                    Deployment deployment = repositoryService.createDeployment().name(model.getName()).addInputStream(processName,processNameByte)
                   .addInputStream(processPng,processPngByte).deploy();
                   LOGGER.info("部署成功，部署ID=" + deployment.getId());
                   jsonObject.put("success",true);
                }
            } catch (Exception e) {
                jsonObject.put("success",false);
                LOGGER.error("Error creating model JSON", e);
                throw new ActivitiException("Error creating model JSON", e);
            }
        }
        return CommonResult.success(jsonObject);
    }

    /**
     * 导出bpmn 文件
     * @param modelId
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/export",method = RequestMethod.GET)
    public void export(@RequestParam(value="modelId") String modelId, HttpServletResponse response) throws IOException {
            Model modelData = repositoryService.getModel(modelId);
            BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
            JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
            BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);

            // 流程非空判断
            if (!CollectionUtils.isEmpty(bpmnModel.getProcesses())) {
                BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
                byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);

                ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
                String filename = bpmnModel.getMainProcess().getId() + ".bpmn";
                response.setHeader("Content-Disposition", "attachment; filename=" + filename);
                IOUtils.copy(in, response.getOutputStream());
                response.flushBuffer();
            }
    }

    /**
     * 删除流程模型
     * @param map
     */
    @RequestMapping(value = "/delete",method = RequestMethod.POST)
    public CommonResult<JSONObject>  delete(@RequestBody Map<String,Object>map)  {
        JSONObject result=new JSONObject();
        String id=map.get("id").toString();
        repositoryService.deleteModel(id);
        result.put("success",true);
        return CommonResult.success(result);
    }

}
